package manage.modules.worker.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import manage.commons.Constants;
import manage.commons.utils.Pager;
import manage.commons.utils.TableNameUtil;
import manage.modules.BaseService;
import manage.modules.dept.model.Dept;
import manage.modules.dept.model.GroupOfDept;
import manage.modules.group.model.Group;
import manage.modules.group.model.WorkerOfGroup;
import manage.modules.role.model.Role;
import manage.modules.worker.model.Worker;
import manage.modules.worker.model.WorkerInfo;
import manage.modules.worker.model.WorkerOfRole;
import manage.modules.worker.service.WorkerService;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.ParameterizedSingleColumnRowMapper;

public class WorkerServiceImpl implements WorkerService {
	private static final String WORKER_TABLE_PRIMARY = "workerId";
	private static final String WORKER_CACHE_KEY = "allWorker";
	private BaseService baseService;

	private ParameterizedRowMapper<Worker> rm = ParameterizedBeanPropertyRowMapper
			.newInstance(getClazz());

	@Override
	public Worker select(Long workerId) {
		return baseService.select(WORKER_TABLE_PRIMARY, workerId, getClazz());
	}

	@Override
	public int insert(Worker worker) {
		int count = baseService.insert(worker);
		clearCacheByCount(count);
		return count;
	}

	@Override
	public int update(Worker worker) {
		int count = baseService.updateFields(WORKER_TABLE_PRIMARY,
				worker.getWorkerId(), worker);
		clearCacheByCount(count);
		return count;
	}

	@Override
	public int delete(Long workerId) {
		int count = baseService.delete(WORKER_TABLE_PRIMARY, workerId,
				getClazz());
		baseService.delete(WORKER_TABLE_PRIMARY, workerId, WorkerOfRole.class);
		baseService.delete(WORKER_TABLE_PRIMARY, workerId, WorkerOfGroup.class);
		clearCacheByCount(count);
		return count;
	}

	@Override
	public List<Worker> listAll() {
		List<Worker> allWorker = (List<Worker>) baseService.getListByCache(
				WORKER_CACHE_KEY, getClazz());
		if (CollectionUtils.isEmpty(allWorker)) {
			allWorker = baseService.listAll(getClazz());
			if (CollectionUtils.isNotEmpty(allWorker)) {
				baseService.setCache(WORKER_CACHE_KEY, allWorker);
			}
		}
		return allWorker;
	}

	@Override
	public int insertWorkerOfGroup(WorkerOfGroup workerOfGroup) {
		return baseService.insert(workerOfGroup);
	}

	@Override
	public void insertWorkerOfGroups(Long workerId, List<Long> groupIds) {
		if (CollectionUtils.isNotEmpty(groupIds)) {
			for (Long groupId : groupIds) {
				WorkerOfGroup workerOfGroup = new WorkerOfGroup();
				workerOfGroup.setWorkerId(workerId);
				workerOfGroup.setGroupId(groupId);
				insertWorkerOfGroup(workerOfGroup);
			}
		}
	}

	@Override
	public void deleteWorkerOfGroups(Long workerId, List<Long> groupIds) {
		if (CollectionUtils.isNotEmpty(groupIds)) {
			for (Long groupId : groupIds) {
				WorkerOfGroup workerOfGroup = new WorkerOfGroup();
				workerOfGroup.setWorkerId(workerId);
				workerOfGroup.setGroupId(groupId);
				deleteWorkerOfGroup(workerOfGroup);
			}
		}
	}

	@Override
	public int deleteWorkerOfGroup(WorkerOfGroup workerOfGroup) {
		Map<String, Object> gOfDept = baseService.comparePojo(null, workerOfGroup);
		return baseService.deleteByFields(gOfDept, WorkerOfGroup.class);
	}

	@Override
	public boolean exists(Long workerId) {
		return baseService.exists(WORKER_TABLE_PRIMARY, workerId, getClazz());
	}

	@Override
	public List<Group> listWorkerOfGroup(Long workerId) {
		List<WorkerOfGroup> wgList = baseService.listByField(
				WORKER_TABLE_PRIMARY, workerId, WorkerOfGroup.class);
		List<Group> groups = new ArrayList<Group>();
		for (WorkerOfGroup wgMap : wgList) {
			Group group = baseService.select("groupId", wgMap.getGroupId(),
					Group.class);
			groups.add(group);
		}
		return groups;
	}

	@Override
	public List<Role> listWorkerOfRole(Long workerId) {
		String cacheKey = Constants.WORKER_ROLE_PRIFX + workerId;
		List<Role> roles = baseService.getListByCache(cacheKey, Role.class);
		if (CollectionUtils.isEmpty(roles)) {
			List<WorkerOfRole> wrList = baseService.listByField(
					WORKER_TABLE_PRIMARY, workerId, WorkerOfRole.class);
			if (CollectionUtils.isNotEmpty(wrList)) {
				roles = new ArrayList<Role>();
				for (WorkerOfRole wrMap : wrList) {
					Role role = baseService.select("roleId", wrMap.getRoleId(),
							Role.class);
					roles.add(role);
				}
				if (CollectionUtils.isNotEmpty(roles)) {
					baseService.setCache(cacheKey, roles);
				}
			}
		}
		return roles;
	}

	@Override
	public List<Dept> listWorkerOfDept(Long workerId) {
		List<Group> wgList = listWorkerOfGroup(workerId);
		List<Dept> depts = new ArrayList<Dept>();
		List<Long> ids = new ArrayList<Long>();
		for (Group group : wgList) {
			List<GroupOfDept> gOfdList = baseService.listByField("groupId",
					group.getGroupId(), GroupOfDept.class);
			for (GroupOfDept groupOfDept : gOfdList) {
				long deptId = groupOfDept.getDeptId();
				Dept dept = baseService.select("deptId", deptId, Dept.class);
				if (null != dept) {
					if (ids.size() > 0) {
						for (long id : ids) {
							if (!StringUtils.equals(String.valueOf(deptId),
									String.valueOf(id))) {
								depts.add(dept);
								break;
							}
						}
					} else {
						depts.add(dept);
					}
					ids.add(dept.getDeptId());
				}
			}
		}
		return depts;
	}

	@Override
	public void query(Map<String, String> param, Pager<Worker> pager) {
		StringBuilder sql = new StringBuilder(1000);
		sql.append(
				"select distinct w.* from  "
						+ TableNameUtil.getTableName(Worker.class) + " w ")
				.append(" left join "
						+ TableNameUtil.getTableName(WorkerOfGroup.class)
						+ " wg on wg.workerId=w.workerId")
				.append(" left join "
						+ TableNameUtil.getTableName(GroupOfDept.class)
						+ " gd on gd.deptId=wg.groupId").append(" where 1 = 1");
		if (MapUtils.isNotEmpty(param)) {
			if (StringUtils.isNotBlank(param.get("workerId"))) {
				sql.append(" and w.workerId like '%" + param.get("workerId")
						+ "%'");
			}
			if (StringUtils.isNotBlank(param.get("workerName"))) {
				sql.append(" and w.workerName like '%"
						+ param.get("workerName") + "%'");
			}
			if (StringUtils.isNotBlank(param.get("groupId"))) {
				sql.append(" and wg.groupId like '%" + param.get("groupId")
						+ "%'");
			}
			if (StringUtils.isNotBlank(param.get("deptId"))) {
				sql.append(" and gd.deptId like '%" + param.get("deptId")
						+ "%'");
			}
			if (StringUtils.isNotBlank(param.get("rank"))) {
				sql.append(" and w.rank = " + param.get("rank"));
			}
		}
		pager.setRowCount(baseService.getJdbcOperations().queryForLong(
				baseService.getCountSql(sql.toString())));
		sql.append(" limit ?,?");
		pager.setList(baseService.getJdbcOperations().query(sql.toString(), rm,
				pager.getRowOffset(), pager.getPageSize()));
	}

	@Override
	public List<Worker> listWorkerByDeptId(Long deptId) {
		StringBuilder sql = new StringBuilder(1000);
		sql.append("select w.* from `groupofdept` gd ")
				.append(" join "
						+ TableNameUtil.getTableName(WorkerOfGroup.class)
						+ " wg on gd.deptId=wg.groupId")
				.append(" join " + TableNameUtil.getTableName(Worker.class)
						+ " w on wg.workerId=w.workerId")
				.append(" where gd.deptId = ?");
		return baseService.getJdbcOperations()
				.query(sql.toString(), rm, deptId);
	}

	@Override
	public List<Worker> listWorkerByGroupId(Long groupId) {
		String sql = "select w.* from "
				+ TableNameUtil.getTableName(WorkerOfGroup.class) + " wg join "
				+ TableNameUtil.getTableName(Worker.class)
				+ " w on wg.workerId=w.workerId  where wg.groupId = ?";
		return baseService.getJdbcOperations().query(sql, rm, groupId);
	}

	@Override
	public List<Long> listGroupIdByWorkerId(Long workerId) {
		String sql = "select groupId from "
				+ TableNameUtil.getTableName(WorkerOfGroup.class)
				+ " where workerId = ?";
		return baseService.getJdbcOperations().query(sql,
				ParameterizedSingleColumnRowMapper.newInstance(Long.class),
				workerId);
	}

	@Override
	public Long getCountOfAll() {
		return baseService.countOfAll(getClazz());
	}

	@Override
	public Map<String, Object> getWorkerOrganization(WorkerInfo worker,
			Integer[] ability) {
		Map<String, Object> result = new HashMap<String, Object>();
		// 员工级别
		int rank = worker.getRank();
		// 分别把三个表数据直接读出来
		String dSql = "select deptId, replace(deptName,'\r\n','') as deptName,ability from "
				+ TableNameUtil.getTableName(Dept.class) + " d where 1=1";
		String gSql = "select  gd.deptId as deptId,g.groupId as groupId, replace(g.groupName,'\r\n','') as groupName"
				+ " from "
				+ TableNameUtil.getTableName(Dept.class)
				+ " d,"
				+ TableNameUtil.getTableName(GroupOfDept.class)
				+ " gd, "
				+ TableNameUtil.getTableName(Group.class)
				+ " g where d.deptId=gd.deptId and gd.groupId = g.groupId";
		String wSql = "select distinct wg.groupId as groupId, w.workerId, replace(w.workerName,'\r\n','') as workerName"
				+ " from `worker` w,"
				+ TableNameUtil.getTableName(GroupOfDept.class)
				+ " gd,"
				+ TableNameUtil.getTableName(WorkerOfGroup.class)
				+ " wg,"
				+ TableNameUtil.getTableName(Dept.class)
				+ " d"
				+ " where d.deptId=gd.deptId and gd.groupId = wg.groupId and wg.workerId=w.workerId";
		// 查询结果
		List<Map<String, Object>> dResult = null;
		List<Map<String, Object>> gResult = null;
		List<Map<String, Object>> wResult = null;
		// 如果是总监或者全部显示
		if (rank == Constants.DIRECTOR) {
			String abilityParams = paramsToString("d.ability", ability);
			dSql += abilityParams;
			gSql += abilityParams;
			wSql += abilityParams;
			// 部门
			dResult = baseService.getJdbcOperations().queryForList(
					dSql + " order by d.ability,d.deptName desc,d.deptId");
			// 组别
			gResult = baseService.getJdbcOperations().queryForList(
					gSql + " order by d.deptId, g.groupId");
			// 人员
			wResult = baseService.getJdbcOperations().queryForList(
					wSql + " order by gd.groupId, w.workerId");

			// 前台识别
			result.put("type", Constants.DIRECTOR);
			result.put("dResult", dResult);
			result.put("gResult", gResult);
			result.put("wResult", wResult);
			return result;
		} else if (rank == Constants.MANAGER) {// 如果是部门经理
			List<Dept> depts = worker.getDepts();
			Long[] dIds = new Long[depts.size()];
			for (int i = 0; i < dIds.length; i++) {
				dIds[i] = depts.get(i).getDeptId();
			}
			String deptStr = paramsToString("d.deptId", dIds);
			dSql += deptStr;
			gSql += deptStr;
			wSql += deptStr;
			dResult = baseService.getJdbcOperations().queryForList(
					dSql + " order by d.ability,d.deptName desc,d.deptId");
			// 组别
			gResult = baseService.getJdbcOperations().queryForList(
					gSql + " order by g.groupId");
			// 人员
			wResult = baseService.getJdbcOperations().queryForList(
					wSql + " order by wg.groupId, w.workerId");
			// 前台识别
			result.put("type", Constants.MANAGER);
			result.put("dResult", dResult);
			result.put("gResult", gResult);
			result.put("wResult", wResult);
			return result;
		} else if (rank == Constants.LEADER) {// 如果是组长
			List<Dept> depts = worker.getDepts();
			Long[] dIds = new Long[depts.size()];
			for (int i = 0; i < dIds.length; i++) {
				dIds[i] = depts.get(i).getDeptId();
			}
			List<Group> groups = worker.getGroups();
			Long[] gIds = new Long[groups.size()];
			for (int i = 0; i < gIds.length; i++) {
				gIds[i] = groups.get(i).getGroupId();
			}
			dSql += paramsToString("d.deptId", dIds);
			gSql += paramsToString("g.groupId", gIds);
			wSql += paramsToString("wg.groupId", gIds);
			// 部门
			dResult = baseService.getJdbcOperations().queryForList(
					dSql + " order by d.ability,d.deptName desc,d.deptId");
			// 组别
			gResult = baseService.getJdbcOperations().queryForList(
					gSql + " order by g.groupId");
			// 人员
			wResult = baseService.getJdbcOperations().queryForList(
					wSql + " order by wg.groupId, w.workerId");
			// 前台识别
			result.put("type", Constants.LEADER);
			result.put("dResult", dResult);
			result.put("gResult", gResult);
			result.put("wResult", wResult);
			return result;
		} else {// 其他员工
			List<Dept> depts = worker.getDepts();
			Long[] dIds = new Long[depts.size()];
			for (int i = 0; i < dIds.length; i++) {
				dIds[i] = depts.get(i).getDeptId();
			}
			List<Group> groups = worker.getGroups();
			Long[] gIds = new Long[groups.size()];
			for (int i = 0; i < gIds.length; i++) {
				gIds[i] = groups.get(i).getGroupId();
			}
			dSql += paramsToString("d.deptId", dIds);
			gSql += paramsToString("g.groupId", gIds);
			wSql += " and w.workerId = " + worker.getWorkerId();
			// 部门
			dResult = baseService.getJdbcOperations().queryForList(
					dSql + " order by d.ability,d.deptName desc,d.deptId");
			// 组别
			gResult = baseService.getJdbcOperations().queryForList(
					gSql + " order by g.groupId");
			// 人员
			wResult = baseService.getJdbcOperations().queryForList(
					wSql + " order by wg.groupId, w.workerId");
			// 前台识别
			result.put("type", -1000);
			result.put("dResult", dResult);
			result.put("gResult", gResult);
			result.put("wResult", wResult);
			return result;
		}
	}

	private <T> String paramsToString(String field, T[] a) {
		if (ArrayUtils.isNotEmpty(a)) {
			StringBuilder bf = new StringBuilder();
			for (int i = 0; i < a.length; i++) {
				if (bf.length() > 0) {
					bf.append(" or ");
				}
				bf.append(field + "=" + a[i]);
			}
			return " and (" + bf.toString() + ")";
		}
		return "";

	}

	@Override
	public WorkerInfo selectWorkerInfo(Long workerId) {
		Worker worker = select(workerId);
		WorkerInfo workerInfo = new WorkerInfo();
		try {
			BeanUtils.copyProperties(workerInfo, worker);
			workerInfo.setGroups(listWorkerOfGroup(workerId));
			workerInfo.setDepts(listWorkerOfDept(workerId));
			return workerInfo;
		} catch (Exception e) {
		}
		return null;
	}

	private void clearCacheByCount(int count) {
		if (count > 0) {
			baseService.clearCache(WORKER_CACHE_KEY);
		}
	}

	public Class<Worker> getClazz() {
		return Worker.class;
	}

	public void setBaseService(BaseService baseService) {
		this.baseService = baseService;
	}

}
